  /*
  Embedded course ECS358
  
  This Spirometer meters air preassure difference made by
  human blow in pipe.
  This preassure difference is calculated to airflow and airvolume
  and displayed on monitor or display.
  
  Pipe has different surface area (flow area) and resistance which causes
  the difference in preassure
  
  Members:
  
  Gillen Luro (France)
  Valtteri Isomäki (Finland)
  
  */
  
  //include the encanhced ADC library
  #include <eRCaGuy_analogReadXXbit.h>
  
  //instantiate an object of this library class; call it "adc"
  eRCaGuy_analogReadXXbit adc;
  // Global variables
  const unsigned int sensor_pin = A3;       // preassure sensor analog pin
  const float MAX_READING_12_bit = 4092.0;  
  
  unsigned int start_time;
  unsigned int interval_time; 
  unsigned int stop_time; 
  unsigned int time_of_event;
  float airflow;
  float air_volume;
  
  void setup() {
    Serial.begin(115200);
    //Serial.print("start! \n\n");
    
  }
  
  void loop() {
    
    float voltage = ad_conversion();
    boolean i = 0;
    
    while(voltage > 1.0) {            // measurement is on-going when treshold is over x.x Volts
      if(i == 0) {                    // Do once in this while loop
        i = 1;
        start_time = millis();        // for curiosity measure how long the expiration lasts: stop_time - start_time
        interval_time = millis();
      }
      
      unsigned int current_time = millis();
      if((current_time - interval_time) >= 200) {  // Do the integration every 200ms       
        Serial.print("air volume : ");
        Serial.println(math_air_volume(airflow));  // send the cumulative air_volume
        interval_time = current_time;
      }
      
      voltage = ad_conversion();
      float pressure = math_pressure(voltage);
      airflow = math_airflow(pressure);
            
      Serial.print("voltage : ");
      Serial.println(voltage);                    // send voltage (unneccesary)
      Serial.print("pressure : ");
      Serial.println(pressure);                  // send pressure (unimportant)
      Serial.print("airflow : ");      
      Serial.println(airflow);                   // send airflow 
      Serial.print("current time : ");
      Serial.println(current_time - start_time); // send the time of current measurement
      
        
    }
    
    if(i == 1) {                                  // do this right after previous while() loop ends
      time_of_event = 0;                          // reset the time_of_event
      stop_time = millis();                       // set the stop time
      if((stop_time - start_time) > 4000) {       // send time of event only if over 4 seconds
        time_of_event = stop_time - start_time;     // measure how long the event lasts (milliseconds)
        Serial.print("time_of_event : ");
        Serial.println(time_of_event);              // send the expiration time 
      }
    }
  }
  
  /*.............FUNCTIONS.............*/
  
  float ad_conversion() {                                           // reads sensor value and converts it to voltage
    float analog_reading = adc.analogReadXXbit(sensor_pin, 12, 10);  // pin A0, 12bit, 10 sample average
    float Vout = analog_reading / 4095 * 5.0;
    return Vout;                                                    // returns voltage
  }
  
  float math_pressure(float Vout){                          // Vout (of sensor) is given to this function
     // Vout equals Vs(0.09*Pressure + 0.04) ± (5% Vfss)    // this is the transfer function, Vs = 5VDC +-0.25V
    float pressure = (Vout / 5 - 0.04)/0.09;                // constants may change due calibration
    return pressure;                                        // returns pressure ( kilopascals )
  }
  
  float math_airflow(float pressure) {        // pressure is given to this function
    float alpha = 1.0;                        // constants for linear function
    float beta = 1.0; 
    airflow = alpha * pressure + beta;
    return airflow;                           // returns airflow ( milliLitres per second )
  }
  
  float math_air_volume(float airflow) {       // airflow is given to this function
    air_volume = air_volume + 0.200 * airflow; // 200ms * airflow (unit?)
    return air_volume;                         // returns air volume ( millilitres ) 
  }
  
